-
Notifications
You must be signed in to change notification settings - Fork 6
DEVP-421: Add visual feedback when entering API Token #37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DEVP-421: Add visual feedback when entering API Token #37
Conversation
Implements a new token input utility that provides visual feedback for API token entry with intelligent paste detection: - Shows asterisks (****) for manually typed characters - Detects long paste operations (>50 chars) via bracketed paste mode - Displays inline confirmation with character count in gray text - Combines typed and pasted content seamlessly - Handles very long tokens (750+ chars) without truncation - Avoids terminal buffer limitations of character-by-character input Technical Implementation: - Uses prompt_toolkit for password input with bracketed paste support - Custom key bindings to detect and handle paste events - ANSI escape sequences for inline confirmation prompt - Proper error handling and retry logic Dependencies: - Added prompt-toolkit>=3.0.0 - Updated mypy configuration and pre-commit hooks Testing: - 13 comprehensive unit tests with 61% code coverage - Tests cover typing, pasting, confirmation, retries, and error cases - All tests pass with proper mocking of terminal interaction Related to PR #28 (reverted in #29 due to pwinput truncation issues) This solution resolves the truncation problem by using bracketed paste mode instead of character-by-character input processing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Replaced click.prompt with get_token_with_smart_paste utility in both token prompt locations (_create_profile_with_env_vars and _create_new_profile). This provides visual feedback (asterisk masking) and handles long token pastes without truncation. Changes: - Added asyncio import and get_token_with_smart_paste import to manager.py - Replaced token prompts with asyncio.to_thread(get_token_with_smart_paste) - Updated 4 tests to mock get_token_with_smart_paste instead of click.prompt All 944 tests passing. Type checking, linting, and formatting all pass. Fixes DEVP-498 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces smart token input functionality with paste detection to improve the user experience when entering API tokens. The implementation uses prompt-toolkit to detect when users paste long tokens and provides a confirmation mechanism to avoid terminal buffer issues.
Key changes:
- Added
get_token_with_smart_paste()function with paste detection for tokens exceeding configurable threshold - Integrated the new token input method into
ConfigManagerfor profile creation flows - Added comprehensive test coverage for the new functionality
Reviewed Changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| uv.lock | Adds prompt-toolkit v3.0.52 and its wcwidth dependency to the lock file |
| pyproject.toml | Declares prompt-toolkit>=3.0.0 as a project dependency and adds mypy ignore configuration |
| .pre-commit-config.yaml | Adds prompt-toolkit>=3.0.0 to pre-commit hook dependencies |
| src/workato_platform_cli/cli/utils/token_input.py | New module implementing smart token input with paste detection and confirmation |
| src/workato_platform_cli/cli/utils/init.py | Exports the new token input functions |
| src/workato_platform_cli/cli/utils/config/manager.py | Replaces click.prompt with get_token_with_smart_paste for token input |
| tests/unit/utils/test_token_input.py | Comprehensive test suite for the new token input functionality |
| tests/unit/config/test_manager.py | Updates tests to mock get_token_with_smart_paste instead of click.prompt |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| async with Workato(configuration=api_config) as workato_api_client: | ||
| user_info = await workato_api_client.users_api.get_workspace_details() |
Copilot
AI
Nov 6, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing exception handling for the API authentication call. The _prompt_and_validate_credentials method (lines 539-546) includes a try-except block to catch authentication failures and provide user-friendly error messages. The same error handling should be added here for consistency and better user experience when authentication fails.
| async with Workato(configuration=api_config) as workato_api_client: | |
| user_info = await workato_api_client.users_api.get_workspace_details() | |
| try: | |
| async with Workato(configuration=api_config) as workato_api_client: | |
| user_info = await workato_api_client.users_api.get_workspace_details() | |
| except Exception as e: | |
| click.echo(f"❌ Authentication failed: {e}") | |
| sys.exit(1) |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hovu96 :
- Please fix the failing test. I think this started failing when I merged in main.
- Take a look at the copilot suggestion
- We've got some inconsistent error messages:
- token_input.py:58: "❌ Token cannot be empty"
- manager.py:581: "❌ No token provided"
- The value 50 appears in multiple places. Consider defining as a module constant:
DEFAULT_PASTE_THRESHOLD = 50 # Chars to trigger paste confirmation
- Remove try-except wrapper in _prompt_and_validate_credentials that was masking UnauthorizedException, preventing proper error handling - Replace all sys.exit(1) calls with click.ClickException for validation errors and user cancellations - Remove unused sys import - Update tests to expect click.ClickException instead of SystemExit This allows @handle_api_exceptions and @handle_cli_exceptions decorators to properly catch and format all errors consistently. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
- Change "No token provided" to "API token cannot be empty" for consistency - Change prompt_text from "Workato API token" to "API token" (context is already clear from CLI name) - Update token_input.py to dynamically use prompt_text in error messages instead of hardcoded "Token" - Update tests to expect new consistent messaging All token-related error messages now consistently use "API token" across the codebase. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
hovu96
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Fixed all tests failing due to merge with main.
- Copilot suggestion - Evaluated but decided against it. The broad except would mask other errors. Better to let SDK exceptions propagate naturally. I even removed try-except another place.
- Inconsistent error messages - Standardized everything to "API token cannot be empty" across the codebase (token_input.py, manager.py, all tests).
- Magic number 50 - Extracted to DEFAULT_PASTE_THRESHOLD = 50 constant in token_input.py, used in function default parameter.
Also replaced all sys.exit(1) with click.ClickException for proper error propagation
Summary
workato initcommand (DEVP-498)Changes
New Utility Module (
token_input.py)get_token_with_smart_paste()function with:Integration into
workato initclick.promptwithget_token_with_smart_pastein two locations:_create_profile_with_env_vars()(line 446)_create_new_profile()(line 491)asyncio.to_thread()to bridge sync function into async contextTest Plan
Workato API token: (📋 850 chars pasted) - confirm? [Y/n]:Why This Approach?
pwinputwhich reads chars individually withgetch(), prompt_toolkit handles pastes nativelyRelated Issues
🤖 Generated with Claude Code